page.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import { notFound } from "next/navigation";
  2. import { Suspense } from "react";
  3. import {
  4. RelatedProductSkeleton,
  5. } from "@/components/common/skeleton/ProductSkeleton";
  6. import { BASE_SCHEMA_URL, PRODUCT_TYPE } from "@/utils/constants";
  7. import { GET_PRODUCT_BY_URL_KEY } from "@/graphql";
  8. import {serverGraphqlFetch} from "@utils/bagisto/index";
  9. import type {
  10. ProductOption,
  11. SingleProductResponse,
  12. ProductMediaType,
  13. } from "@components/catalog/type";
  14. import { RelatedProductsSection } from "@components/catalog/product/RelatedProductsSection";
  15. import { ProductMedia } from "@/app/(public)/product/_components/ProductMedia";
  16. import { ProductInformation } from "@/app/(public)/product/_components/ProductInformation";
  17. import { ProductDetail } from "@/app/(public)/product/_components/ProductDetail";
  18. import ProductDescription from "../_components/ProductDescription";
  19. import SwitchButton from "../_components/SwitchButton";
  20. import ShopServicePanel from "../_components/ShopServicePanel";
  21. import Recommend from "../_components/youmaylike/Recommend"
  22. import { formatFlexibleVariants } from "@/utils/variantTools";
  23. // export const dynamic = 'auto'
  24. // // 'auto' | 'force-dynamic' | 'error' | 'force-static'
  25. export const dynamic = "force-dynamic";
  26. //动态路由中的参数 -- params
  27. export default async function ProductPage({
  28. params,
  29. }: {
  30. params: Promise<{ urlProduct: string[] }>;
  31. searchParams: Promise<{ type: string }>;
  32. }) {
  33. const { urlProduct } = await params;
  34. const fullPath = urlProduct.join("/");
  35. const resProductData = await serverGraphqlFetch<SingleProductResponse,{urlKey: string;}>({
  36. // urlKey, // 产品名称
  37. query: GET_PRODUCT_BY_URL_KEY, // gql查询语句
  38. variables:{
  39. urlKey: fullPath
  40. },
  41. takeAuthorization: false,
  42. cache: 'no-cache'
  43. });
  44. console.log("productCustomerFeatures----------------------",resProductData);
  45. const product = resProductData.data?.product;
  46. const fetchProductError = resProductData.error;
  47. if (fetchProductError && fetchProductError.extensions.status === 404) return notFound();
  48. if(!product) throw new Error(fetchProductError?.message ?? 'Get product data failed');
  49. const questionTotal = 73;
  50. // JSON-LD数据格式,便于搜索引擎识别页面信息,利于seo
  51. const productJsonLd = {
  52. "@context": BASE_SCHEMA_URL,
  53. "@type": PRODUCT_TYPE,
  54. name: product?.name,
  55. description: product?.description,
  56. sku: product?.sku,
  57. };
  58. const mediaImgs = (product?.images?.edges ?? []).map(
  59. (edge: { node: ProductMediaType }) => {
  60. return edge.node;
  61. },
  62. );
  63. const productOptions: ProductOption[] = product?.productOptions
  64. ? JSON.parse(product?.productOptions)
  65. : [];
  66. const flexibleVariants = formatFlexibleVariants(product?.flexibleVariants);
  67. return (
  68. <>
  69. <script //SEO
  70. dangerouslySetInnerHTML={{
  71. __html: JSON.stringify(productJsonLd),
  72. }}
  73. type="application/ld+json"
  74. />
  75. <div className="w-full">
  76. <ProductMedia mediaData={mediaImgs} />
  77. </div>
  78. <div className="">
  79. <ProductInformation
  80. key={product._id}
  81. productId={product._id}
  82. name={product?.name || ""}
  83. productOptions={productOptions}
  84. flexibleVariants={flexibleVariants}
  85. isSaleable={product.isSaleable}
  86. shortDescription={product.shortDescription || ""}
  87. />
  88. <ShopServicePanel />
  89. <ProductDescription htmlString={product?.feature || ""} />
  90. <SwitchButton
  91. productId={"3792"} //|| String(product._id)
  92. questionTotal={questionTotal}
  93. questionList={["aaa"]}
  94. />
  95. <ProductDetail detail={product.description || ""} />
  96. <Recommend/>
  97. </div>
  98. <Suspense fallback={<RelatedProductSkeleton />}>
  99. <RelatedProductsSection fullPath={fullPath} />
  100. </Suspense>
  101. </>
  102. );
  103. }